package org.nlp2rdf.navigator.component.store;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.nlp2rdf.navigator.client.common.ConceptDTO;
import org.nlp2rdf.navigator.client.common.LearnedConceptDTO;
import org.nlp2rdf.navigator.client.common.RelatedConceptsDTO;
import org.nlp2rdf.navigator.client.common.StoredConceptDTO;
import org.nlp2rdf.navigator.client.common.RelatedConceptsDTO.StrategyDTO;
import org.nlp2rdf.navigator.component.Component;
import org.nlp2rdf.navigator.component.exception.ConceptSavingFailedException;

/**
 * This implementation encapsulates different strategies for finding related
 * concepts
 * 
 * @author Sebastian Hellmann <hellmann@informatik.uni-leipzig.de>
 * 
 */
public abstract class Store extends Component implements IStore {
	private static final Logger logger = Logger.getLogger(Store.class);
	
	//TODO make classPrefix configurable
	private String classPrefix = "http://nke.aksw.org/ontology/";

    public String generateUriFromLabel(LearnedConceptDTO learnedConcept){
		if (learnedConcept.getLabel() == null) {
			logger.warn("label is null\n" + learnedConcept.toDebugString());
		}
		String encoded = "";
		try {
			encoded = URLEncoder.encode(learnedConcept.getLabel(), "UTF-8")+System.currentTimeMillis();
		} catch (UnsupportedEncodingException e) {
			logger.error("", e);
		}

		return classPrefix + encoded;
		
	}

	protected List<IRelatedConceptStrategy> relatedConceptStrategies = new ArrayList<IRelatedConceptStrategy>();

	protected abstract StoredConceptDTO _saveConcept(LearnedConceptDTO learnedConceptDTO)
			throws ConceptSavingFailedException;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.nlp2rdf.navigator.component.store.IStore#getRelatedConcepts(org.nlp2rdf
	 * .navigator.client.common.LearningResultDTO)
	 */
	public RelatedConceptsDTO getRelatedConcepts(ConceptDTO learningresultDTO) {
		RelatedConceptsDTO ret = new RelatedConceptsDTO();
		for (IRelatedConceptStrategy relatedConceptStrategy : relatedConceptStrategies) {
			for (StrategyDTO s : relatedConceptStrategy.getRelatedConcepts(learningresultDTO)) {
				ret.addStrategy(s);
			}
		}
		return ret;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.nlp2rdf.navigator.component.store.IStore#saveConcept(org.nlp2rdf.
	 * navigator.client.common.LearningResultDTO)
	 */
	public StoredConceptDTO saveConcept(LearnedConceptDTO learningResultDTO) throws ConceptSavingFailedException {
		StoredConceptDTO st;
        try {
			st = _saveConcept(learningResultDTO);
            updateRelatedConceptStrategies(st);
		} catch (ConceptSavingFailedException e) {
			logger.error(learningResultDTO.toDebugString(), e);
			throw e;
		}
        return st;

	}

    protected void updateRelatedConceptStrategies(StoredConceptDTO st ){
        for (IRelatedConceptStrategy relconstra : relatedConceptStrategies) {
				relconstra.update(st);
			}
    }

    protected void updateRelatedConceptStrategies( Map<String, StoredConceptDTO> conceptMap ){
        for (String s:conceptMap.keySet()){
            StoredConceptDTO stc = conceptMap.get(s);
            if(stc!=null){
                updateRelatedConceptStrategies(stc);
            }
        }
    }


	public List<IRelatedConceptStrategy> getRelatedConceptStrategies() {
		return relatedConceptStrategies;
	}

	public void setRelatedConceptStrategies(List<IRelatedConceptStrategy> relatedConceptStrategies) {
		this.relatedConceptStrategies = relatedConceptStrategies;
	}

}
